﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace StructureDiagram
{
    public class Diagram
    {
        List<DiagramElement> elements;

        //
        
        /// <summary>
        /// Creation of empty diagram
        /// </summary>
        public Diagram()
        {
            elements = new List<DiagramElement>();
        }

        /// <summary>
        /// Getting all of the diagram elements
        /// </summary>
        /// <returns>Returns all of the diagram elements</returns>
        public List<DiagramElement> GetAllElements()
        {
            return elements;
        }

        /// <summary>
        /// Getting element of diagram without previous elements
        /// </summary>
        /// <returns>
        /// Returns diagram element without previous elements
        /// or returns null if diagram hasn't got element
        /// without previous elements
        /// </returns>
        public DiagramElement GetFirstElement()
        {
            foreach (DiagramElement element in elements)
            {
                if (!element.HasPreviousElements(false))
                    return element;
            }

            return null;
        }

        /// <summary>
        /// Add element to the diagram and connect them with two other elements
        /// </summary>
        /// <param name="element">New element of the diagram</param>
        /// <param name="previousElement">Previous element of the diagram (may be null)</param>
        /// <param name="nextElement">Next element of the diagram (may be null)</param>
        public void AddElement(DiagramElement element, DiagramElement previousElement, 
            DiagramElement nextElement)
        {
            List<DiagramElement> previousElements = new List<DiagramElement>();
            List<DiagramElement> nextElements = new List<DiagramElement>();

            if (previousElement != null)
                previousElements.Add(previousElement);

            if (nextElement != null)
                nextElements.Add(previousElement);

            AddElement(element, previousElements, nextElements);
        }

        /// <summary>
        /// Add element without connections to the diagram
        /// </summary>
        /// <param name="element">New element of the diagram</param>
        public void AddElement(DiagramElement element)
        {
            AddElement(element, new List<DiagramElement>(),
                new List<DiagramElement>());
        }

        /// <summary>
        /// Add element to the diagram and connect them with a few other elements
        /// </summary>
        /// <param name="element">New element of the diagram</param>
        /// <param name="previousElement">Previous element of the diagram</param>
        /// <param name="nextElement">Next element of the diagram</param>
        public void AddElement(DiagramElement element, List<DiagramElement> previousElements,
            List<DiagramElement> nextElements)
        {
            foreach (DiagramElement previousElement in previousElements)
            {
                element.ConnectWithPreviousElement(previousElement);

                previousElement.ConnectWithNextElement(element);

                int previousElementIndex = elements.IndexOf(previousElement);
                if (previousElementIndex > 0)
                    elements[previousElementIndex] = previousElement;
                else
                    throw new ArgumentException("Cannot find a previous element: " + 
                        previousElement.ToString());
            }

            foreach (DiagramElement nextElement in nextElements)
            {
                element.ConnectWithNextElement(nextElement);

                nextElement.ConnectWithPreviousElement(element);

                int nextElementIndex = elements.IndexOf(nextElement);
                if (nextElementIndex > 0)
                    elements[nextElementIndex] = nextElement;
                else
                    throw new ArgumentException("Cannot find a next element: " +
                        nextElement.ToString());
            }

            elements.Add(element);
        }
    }
}
